﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CSharpExperiments
{
	public static class Tuples
	{
		public static Tuple<A, B> AsTuple2<A, B>(this Tuple<A, B> tuple)
		{
			return tuple;
		}

		public static Tuple<A, B, C> AsTuple3<A, B, C>(this Tuple<A, B> tuple, C c)
		{
			return Tuple.Create(tuple.Item1, tuple.Item2, c);
		}

		public static Tuple<A, B, C, D> AsTuple4<A, B, C, D>(this Tuple<A, B> tuple, C c, D d)
		{
			return Tuple.Create(tuple.Item1, tuple.Item2, c, d);
		}
		
		public static Tuple<A, B, C, D> AsTuple4<A, B, C, D>(this Tuple<A, B> tuple, Tuple<C, D> cd)
		{
			return Tuple.Create(tuple.Item1, tuple.Item2, cd.Item1, cd.Item2);
		}

		public static Tuple<A, B, C, D, E> AsTuple5<A, B, C, D, E>(this Tuple<A, B> tuple, C c, D d, E e)
		{
			return Tuple.Create(tuple.Item1, tuple.Item2, c, d, e);
		}

		public static Tuple<A, B, C, D, E> AsTuple5<A, B, C, D, E>(this Tuple<A, B> tuple, Tuple<C, D, E> cde)
		{
			return Tuple.Create(tuple.Item1, tuple.Item2, cde.Item1, cde.Item2, cde.Item3);
		}

		public static Tuple<A, B> AsTuple2<A, B, C>(this Tuple<A, B, C> tuple)
		{
			return Tuple.Create(tuple.Item1, tuple.Item2);
		}

		public static Tuple<A, B, C> AsTuple3<A, B, C>(this Tuple<A, B, C> tuple)
		{
			return tuple;
		}

		public static Tuple<A, B, C, D> AsTuple4<A, B, C, D>(this Tuple<A, B, C> tuple, D d)
		{
			return Tuple.Create(tuple.Item1, tuple.Item2, tuple.Item3, d);
		}
		
		public static Tuple<A, B, C, D, E> AsTuple5<A, B, C, D, E>(this Tuple<A, B, C> tuple, D d, E e)
		{
			return Tuple.Create(tuple.Item1, tuple.Item2, tuple.Item3, d, e);
		}
		
		public static Tuple<A, B, C, D, E> AsTuple5<A, B, C, D, E>(this Tuple<A, B, C, D> tuple, E e)
		{
			return Tuple.Create(tuple.Item1, tuple.Item2, tuple.Item3, tuple.Item4, e);
		}

		public static Tuple<A, B> AsTuple2<A, B, C, D>(this Tuple<A, B, C, D> tuple)
		{
			return Tuple.Create(tuple.Item1, tuple.Item2);
		}

		public static Tuple<A, B, C> AsTuple3<A, B, C, D>(this Tuple<A, B, C, D> tuple)
		{
			return Tuple.Create(tuple.Item1, tuple.Item2, tuple.Item3);
		}

		public static Tuple<A, B, C, D> AsTuple4<A, B, C, D>(this Tuple<A, B, C, D> tuple, D d)
		{
			return tuple;
		}
		
		public static Tuple<A, B, C, D, E> AsTuple5<A, B, C, D, E>(this Tuple<A, B, C, D> tuple, D d, E e)
		{
			return Tuple.Create(tuple.Item1, tuple.Item2, tuple.Item3, d, e);
		}
		
		public static Func<Tuple<A>, Z> Tuplize<A, Z>(this Func<A, Z> func)
		{
			return tuple => func(tuple.Item1);
		}

		public static Func<Tuple<A, B>, Z> Tuplize<A, B, Z>(this Func<A, B, Z> func)
		{
			return tuple => func(tuple.Item1, tuple.Item2);
		}

		public static Func<Tuple<A, B, C>, Z> Tuplize<A, B, C, Z>(this Func<A, B, C, Z> func)
		{
			return tuple => func(tuple.Item1, tuple.Item2, tuple.Item3);
		}

		public static Func<Tuple<A, B, C, D>, Z> Tuplize<A, B, C, D, Z>(this Func<A, B, C, D, Z> func)
		{
			return tuple => func(tuple.Item1, tuple.Item2, tuple.Item3, tuple.Item4);
		}

		public static Func<Tuple<A, B, C, D, E>, Z> Tuplize<A, B, C, D, E, Z>(this Func<A, B, C, D, E, Z> func)
		{
			return tuple => func(tuple.Item1, tuple.Item2, tuple.Item3, tuple.Item4, tuple.Item5);
		}

		public static Func<A, Z> Untuplize<A, Z>(this Func<Tuple<A>, Z> func)
		{
			return a => func(Tuple.Create(a));
		}

		public static Func<A, B, Z> Untuplize<A, B, Z>(this Func<Tuple<A, B>, Z> func)
		{
			return (a, b) => func(Tuple.Create(a, b));
		}

		public static Func<A, B, C, Z> Untuplize<A, B, C, Z>(this Func<Tuple<A, B, C>, Z> func)
		{
			return (a, b, c) => func(Tuple.Create(a, b, c));
		}

		public static Func<A, B, C, D, Z> Untuplize<A, B, C, D, Z>(this Func<Tuple<A, B, C, D>, Z> func)
		{
			return (a, b, c, d) => func(Tuple.Create(a, b, c, d));
		}

		public static Func<A, B, C, D, E, Z> Untuplize<A, B, C, D, E, Z>(this Func<Tuple<A, B, C, D, E>, Z> func)
		{
			return (a, b, c, d, e) => func(Tuple.Create(a, b, c, d, e));
		}
	}
}
